#include "spi.h"
#include "gpio.h"
#include "W25Q64.h"

// 片选使能
void W25Q64_CS_Enable(void) 
	{
    HAL_GPIO_WritePin(W25Q64_CS_PORT, W25Q64_CS_PIN, GPIO_PIN_RESET);
}

// 片选失能
void W25Q64_CS_Disable(void) 
	{
    HAL_GPIO_WritePin(W25Q64_CS_PORT, W25Q64_CS_PIN, GPIO_PIN_SET);
}
	
// SPI 发送和接收一个字节
uint8_t W25Q64_SPI_SendByte(uint8_t byte) 
	{
    uint8_t received_byte;
    HAL_SPI_TransmitReceive(&hspi1, &byte, &received_byte, 1, HAL_MAX_DELAY);
    return received_byte;
}
	
void W25Q64_Init(void) 
	{

//    GPIO_InitTypeDef GPIO_InitStruct = {0};

//    // 使能 GPIO 时钟
//    __HAL_RCC_GPIOA_CLK_ENABLE();
//    __HAL_RCC_GPIOB_CLK_ENABLE();

//    // 配置片选引脚
//    GPIO_InitStruct.Pin = W25Q64_CS_PIN;
//    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
//    GPIO_InitStruct.Pull = GPIO_NOPULL;
//    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
//    HAL_GPIO_Init(W25Q64_CS_PORT, &GPIO_InitStruct);

//    // 配置 SPI 引脚 SCK (PB3), MISO (PB4), MOSI (PB5)
//    GPIO_InitStruct.Pin = GPIO_PIN_3 | GPIO_PIN_5;
//    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
//    GPIO_InitStruct.Pull = GPIO_NOPULL;
//    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
//    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

//    GPIO_InitStruct.Pin = GPIO_PIN_4;
//    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
//    GPIO_InitStruct.Pull = GPIO_NOPULL;
//    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

		MX_SPI1_Init();
    // 初始化时片选失能
    W25Q64_CS_Disable();
}


// 初始化 W25Q64

// 读取 W25Q64 设备 ID
void W25Q64_ReadDeviceID(uint8_t *MID, uint16_t *DID) 
	{

    W25Q64_CS_Enable();

    // 发送读取设备 ID 命令
    W25Q64_SPI_SendByte(W25Q64_JEDEC_ID);
    *MID = W25Q64_SPI_SendByte(W25Q64_DUMMY_BYTE);
   	*DID =  W25Q64_SPI_SendByte(W25Q64_DUMMY_BYTE);
   	*DID <<= 8;	
   	*DID |=  W25Q64_SPI_SendByte(W25Q64_DUMMY_BYTE);

    // 读取厂商 ID 和设备 ID
//    W25Q64_SPI_SendByte(0xFF);  // 丢弃厂商 ID
//    device_id = W25Q64_SPI_SendByte(0xFF);

    W25Q64_CS_Disable();

//    return device_id;
}    
	

/**
  * 函    数：W25Q64写使能
  * 参    数：无
  * 返 回 值：无
  */
void W25Q64_WriteEnable(void)
{
	W25Q64_CS_Enable();								//SPI起始
	W25Q64_SPI_SendByte(W25Q64_WRITE_ENABLE);		//交换发送写使能的指令
	W25Q64_CS_Disable();								//SPI终止
}
/**
  * 函    数：W25Q64等待忙
  * 参    数：无
  * 返 回 值：无
  */
void W25Q64_WaitBusy(void)
{
	uint32_t Timeout;
	W25Q64_CS_Enable();								//SPI起始
	W25Q64_SPI_SendByte(W25Q64_READ_STATUS_REGISTER_1);				//交换发送读状态寄存器1的指令
	Timeout = 100000;							//给定超时计数时间
	while ((W25Q64_SPI_SendByte(W25Q64_DUMMY_BYTE) & 0x01) == 0x01)	//循环等待忙标志位
	{
		Timeout --;								//等待时，计数值自减
		if (Timeout == 0)						//自减到0后，等待超时
		{
			/*超时的错误处理代码，可以添加到此处*/
			break;								//跳出等待，不等了
		}
	}
	W25Q64_CS_Disable();								//SPI终止
}

/**
  * 函    数：W25Q64页编程
  * 参    数：Address 页编程的起始地址，范围：0x000000~0x7FFFFF
  * 参    数：DataArray	用于写入数据的数组
  * 参    数：Count 要写入数据的数量，范围：0~256
  * 返 回 值：无
  * 注意事项：写入的地址范围不能跨页
  */
void W25Q64_PageProgram(uint32_t Address, uint8_t *DataArray, uint16_t Count)
{
	uint16_t i;
	
	W25Q64_WriteEnable();										//写使能
	
	W25Q64_CS_Enable();													//SPI起始
	W25Q64_SPI_SendByte(W25Q64_PAGE_PROGRAM);		//交换发送页编程的指令
	W25Q64_SPI_SendByte(Address >> 16);					//交换发送地址23~16位
	W25Q64_SPI_SendByte(Address >> 8);					//交换发送地址15~8位
	W25Q64_SPI_SendByte(Address);							//交换发送地址7~0位
	for (i = 0; i < Count; i ++)					//循环Count次
	{
		W25Q64_SPI_SendByte(DataArray[i]);			//依次在起始地址后写入数据
	}
	W25Q64_CS_Disable();								//SPI终止
	
	W25Q64_WaitBusy();							//等待忙
}

/**
  * 函    数：W25Q64扇区擦除（4KB）
  * 参    数：Address 指定扇区的地址，范围：0x000000~0x7FFFFF
  * 返 回 值：无
  */
void W25Q64_SectorErase(uint32_t Address)
{
	W25Q64_WriteEnable();						//写使能
	
	W25Q64_CS_Enable();								//SPI起始
	W25Q64_SPI_SendByte(W25Q64_SECTOR_ERASE_4KB);	//交换发送扇区擦除的指令
	W25Q64_SPI_SendByte(Address >> 16);				//交换发送地址23~16位
	W25Q64_SPI_SendByte(Address >> 8);				//交换发送地址15~8位
	W25Q64_SPI_SendByte(Address);					//交换发送地址7~0位
	W25Q64_CS_Disable();								//SPI终止
	
	W25Q64_WaitBusy();							//等待忙
}

/**
  * 函    数：W25Q64读取数据
  * 参    数：Address 读取数据的起始地址，范围：0x000000~0x7FFFFF
  * 参    数：DataArray 用于接收读取数据的数组，通过输出参数返回
  * 参    数：Count 要读取数据的数量，范围：0~0x800000
  * 返 回 值：无
  */
void W25Q64_ReadData(uint32_t Address, uint8_t *DataArray, uint32_t Count)
{
	uint32_t i;
	W25Q64_CS_Enable();								//SPI起始
	W25Q64_SPI_SendByte(W25Q64_READ_DATA);			//交换发送读取数据的指令
	W25Q64_SPI_SendByte(Address >> 16);				//交换发送地址23~16位
	W25Q64_SPI_SendByte(Address >> 8);				//交换发送地址15~8位
	W25Q64_SPI_SendByte(Address);					//交换发送地址7~0位
	for (i = 0; i < Count; i ++)				//循环Count次
	{
		DataArray[i] = W25Q64_SPI_SendByte(W25Q64_DUMMY_BYTE);	//依次在起始地址后读取数据
	}
	W25Q64_CS_Disable();								//SPI终止
}